from aliyunsdkcore.client import AcsClient
from aliyunsdkecs.request.v20140526 import AllocatePublicIpAddressRequest
from aliyunsdkecs.request.v20140526 import CreateInstanceRequest
from aliyunsdkecs.request.v20140526 import StartInstanceRequest
from aliyunsdkecs.request.v20140526 import StopInstanceRequest
from aliyunsdkecs.request.v20140526 import DeleteInstanceRequest
from aliyunsdkecs.request.v20140526 import DescribeInstanceAttributeRequest
from aliyunsdkecs.request.v20140526 import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526 import DescribeSecurityGroupsRequest
from aliyunsdkecs.request.v20140526 import DescribeSecurityGroupAttributeRequest
from aliyunsdkecs.request.v20140526 import CreateSecurityGroupRequest
from aliyunsdkecs.request.v20140526 import DeleteSecurityGroupRequest
from aliyunsdkecs.request.v20140526 import AuthorizeSecurityGroupRequest
from aliyunsdkecs.request.v20140526 import AuthorizeSecurityGroupEgressRequest
import json

security_group_name = 'Hello-New-World'


class Instance:
    def __init__(self):
        self.id = ''
        self.ip = ''
        self.region = ''
        self.zone = ''
        self.instance_charge = ''
        self.internet_charge = ''
        self.band = ''
        self.status = ''
        self.type = ''
        self.cpu = ''
        self.memory = ''
        self.image = ''
        self.security = ''
        self.create_time = ''

    def show(self):
        print json.dumps(self.__dict__, sort_keys=True, indent=4)


class EcsClient:
    def __init__(self, ecs_config):
        if ecs_config is None:
            pass


class AliEcsClient(EcsClient):
    def __init__(self, ecs_config):
        EcsClient.__init__(self, ecs_config)
        self.password = ecs_config.ecs_password
        self.band_width = ecs_config.band_width
        self.zone_id = ecs_config.zone_id
        self.instance_type = ecs_config.instance_type
        self.client = AcsClient(ecs_config.access_key, ecs_config.access_key_secret, ecs_config.region_id)

    def alloc_ip(self, instance_id):
        print 'alloc ip...'
        request = AllocatePublicIpAddressRequest.AllocatePublicIpAddressRequest()
        request.set_InstanceId(instance_id)
        self.client.do_action_with_exception(request)
        print 'alloc ip ok'

    def create_instance(self, security_group_id=None):
        print 'create instance...'
        request = CreateInstanceRequest.CreateInstanceRequest()
        request.set_ImageId('centos_7_02_64_20G_alibase_20170818.vhd')
        request.set_InstanceType(self.instance_type)
        request.set_InternetChargeType('PayByTraffic')
        request.set_InstanceChargeType('PostPaid')
        request.set_SystemDiskSize(20)
        if self.band_width is not None:
            request.set_InternetMaxBandwidthOut(self.band_width)
        else:
            request.set_InternetMaxBandwidthOut(5)
        request.set_Password(self.password)
        request.set_SecurityEnhancementStrategy('Active')
        if len(self.zone_id) > 0:
            request.set_ZoneId(self.zone_id)
        if security_group_id is not None:
            request.set_SecurityGroupId(security_group_id)

        response = self.client.do_action_with_exception(request)
        obj = json.loads(response)
        instance_id = obj['InstanceId']
        print 'create instance ok, id is', instance_id
        return instance_id

    def start_instance(self, instance_id):
        print 'start instance %s ...' % instance_id
        request = StartInstanceRequest.StartInstanceRequest()
        request.set_InstanceId(instance_id)

        self.client.do_action_with_exception(request)
        print 'start instance %s ok' % instance_id

    def stop_instance(self, instance_id):
        print 'stop instance %s...' % instance_id
        request = StopInstanceRequest.StopInstanceRequest()
        request.set_InstanceId(instance_id)

        self.client.do_action_with_exception(request)
        print 'stop instance %s ok' % instance_id

    def delete_instance(self, instance_id):
        print 'delete instance %s ...' % instance_id
        request = DeleteInstanceRequest.DeleteInstanceRequest()
        request.set_InstanceId(instance_id)

        self.client.do_action_with_exception(request)
        print 'delete instance %s ok' % instance_id

    def get_instance(self, instance_id):
        request = DescribeInstanceAttributeRequest.DescribeInstanceAttributeRequest()
        request.set_InstanceId(instance_id)

        response = self.client.do_action_with_exception(request)
        obj = json.loads(response)
        instance = Instance()
        instance.id = obj['InstanceId']
        instance.ip = obj['PublicIpAddress']['IpAddress']
        instance.region = obj['RegionId']
        instance.zone = obj['ZoneId']
        instance.instance_charge = obj['InstanceChargeType']
        instance.internet_charge = obj['InternetChargeType']
        instance.band = obj['InternetMaxBandwidthOut']
        instance.status = obj['Status']
        instance.type = obj['InstanceType']
        instance.cpu = obj['Cpu']
        instance.memory = obj['Memory']
        instance.image = obj['ImageId']
        instance.security = obj['SecurityGroupIds']['SecurityGroupId']
        instance.create_time = obj['CreationTime']
        return instance

    def get_instances(self):
        request = DescribeInstancesRequest.DescribeInstancesRequest()
        request.set_PageSize(10)

        response = self.client.do_action_with_exception(request)
        obj = json.loads(response)
        return obj['Instances']['Instance']

    def get_security_groups(self):
        request = DescribeSecurityGroupsRequest.DescribeSecurityGroupsRequest()
        request.set_PageSize(10)

        response = self.client.do_action_with_exception(request)
        obj = json.loads(response)
        return obj['SecurityGroups']['SecurityGroup']

    def get_security_group(self, security_group_id):
        request = DescribeSecurityGroupAttributeRequest.DescribeSecurityGroupAttributeRequest()
        request.set_SecurityGroupId(security_group_id)

        response = self.client.do_action_with_exception(request)
        obj = json.loads(response)
        return obj

    def create_security_group(self):
        print 'create security group...'
        request = CreateSecurityGroupRequest.CreateSecurityGroupRequest()
        request.set_SecurityGroupName(security_group_name)

        response = self.client.do_action_with_exception(request)
        obj = json.loads(response)
        security_group_id = obj['SecurityGroupId']
        print 'create security group ok, id is', security_group_id
        return security_group_id

    def delete_security_group(self, security_group_id):
        print 'delete valid security group %s ...' % security_group_id
        request = DeleteSecurityGroupRequest.DeleteSecurityGroupRequest()
        request.set_SecurityGroupId(security_group_id)

        self.client.do_action_with_exception(request)
        print 'delete security group %s ok' % security_group_id

    def authorize_security_group_in(self, security_group_id):
        print 'authorize security group in %s ...' % security_group_id
        request = AuthorizeSecurityGroupRequest.AuthorizeSecurityGroupRequest()
        request.set_SecurityGroupId(security_group_id)
        request.set_IpProtocol('all')
        request.set_PortRange('-1/-1')
        request.set_SourceCidrIp('0.0.0.0/0')

        self.client.do_action_with_exception(request)
        print 'authorize security group in %s ok' % security_group_id

    def authorize_security_group_out(self, security_group_id):
        print 'authorize security group out %s ...' % security_group_id
        request = AuthorizeSecurityGroupEgressRequest.AuthorizeSecurityGroupEgressRequest()
        request.set_SecurityGroupId(security_group_id)
        request.set_IpProtocol('all')
        request.set_PortRange('-1/-1')
        request.set_DestCidrIp('0.0.0.0/0')

        self.client.do_action_with_exception(request)
        print 'authorize security group out %s ok' % security_group_id

    def create_valid_security_group(self):
        print 'create valid security group...'
        groups = self.get_security_groups()
        group = None
        for security_group in groups:
            print 'Security group with id %s found' % security_group['SecurityGroupId']
            group = self.get_security_group(security_group['SecurityGroupId'])
            if group['SecurityGroupName'] == security_group_name:
                break
            else:
                group = None
        if group is not None:
            security_group_id = group['SecurityGroupId']
            print 'Valid security group %s found, try to check' % security_group_id
            self.authorize_security_group_in(security_group_id)
            self.authorize_security_group_out(security_group_id)
            return security_group_id
        else:
            print 'Valid security group not found, try to create'
            security_group_id = self.create_security_group()
            self.authorize_security_group_in(security_group_id)
            self.authorize_security_group_out(security_group_id)
            return security_group_id
